iT邦幫忙

2024 iThome 鐵人賽

DAY 27
0

前端的 Cache


快取是將網站資料儲存在快取(儲存位置)中的過程,以便為使用者提供更快的存取,提升用戶體驗,減少網頁加載時間;實現快取的方法可以在伺服器端和客戶端實現,前端的部分主要是客戶端快取技術。
流程圖

💡 Cache 之前端 vs 後端
前端: 用於優化用戶端性能,提升用戶體驗,減少靜態資源的加載。
後端: 用於優化伺服器性能,減少資源消耗,減少資料庫連線和計算。(後端小白自學 Laravel-第 17 天:緩存 Cache)

存儲位置

瀏覽器在本機上儲存靜態資源(HTML、CSS、JavaScript、圖片),在後續存取中,瀏覽器將繞過伺服器從快取中提供這些資源。

前端的 Cache 通常存儲在用戶的瀏覽器中,透過 HTTP 頭部(如 Cache-Control)來管理。

流程
Service Worker 是一種在瀏覽器中運行的 JavaScript 代理,可以攔截網絡請求並進行處理。它們常用於實現離線體驗、推送通知和資源緩存等功能。

Cache API 是 Service Worker 中的一部分,它允許開發者緩存請求和響應,透過緩存中提取資源,可以減少網絡請求的數量,從而加快加載速度。

  • step 1:註冊 Service Worker
    在 JavaScript 文件中註冊 Service Worker

    if ('serviceWorker' in navigator) {
        window.addEventListener('load', () => {
            navigator.serviceWorker.register('/service-worker.js')
                .then(registration => {
                    console.log('Service Worker registered with scope:', registration.scope);
                })
                .catch(error => {
                    console.error('Service Worker registration failed:', error);
                });
        });
    }
    
  • step 2:攔截安裝事件
    當 Service Worker 安裝時,緩存所需的資源。

    self.addEventListener('install', (event) => {
        event.waitUntil(
            caches.open('v1').then((cache) => {
                return cache.addAll([
                    '/index.html',
                    '/styles.css',
                    '/script.js',
                    '/image.png'
                ]);
            })
        );
    });
    
  • step 3:攔截請求
    在 fetch 事件中處理網絡請求,從緩存中返回響應,或在緩存未命中的情況下進行網絡請求。

    self.addEventListener('fetch', (event) => {
        event.respondWith(
            caches.match(event.request).then((response) => {
                return response || fetch(event.request);
            })
        );
    });
    

暫存瀏覽器的方法


在瀏覽器裡有不同的機制可以儲存使用者或網站資料,當然也有些儲存限制,以下是這些機制的介紹。
暫存瀏覽器的方法

Cookies

  • 記憶體限制:通常每個 cookie 最多 4KB。

  • 最適合:儲存少量數據,例如使用者首選項或會話令牌。

    // 設定 cookie
    document.cookie = "sessionId=38afes7a83; expires=Thu
    
    // 讀取 cookies
    let cookies = document.cookie.split(';');
    let sessionId = cookies.find(cookie => cookie.includes ('sessionId'));
    

🔔 注意:隨每個 HTTP 請求一起發送,因此如果儲存大量資料可能會影響效能。

LocalStorage

  • 優勢:允許 JavaScript 網站和應用程式在瀏覽器中儲存鍵/ 值數據,且沒有過期日期,即使關閉並重新開啟瀏覽器,資料仍然存在。
  • 記憶體限制:通常每個域大約 5MB。
  • 最適合:儲存跨瀏覽器會話持續存在的非敏感、非結構化資料,非常適合首選項或簡單的客戶端快取。
    const user = {
      name: "kuku",
      age: null,
      email: "[kuku@123.com]"
    };
    
    localStorage.setItem("user", JSON.stringify(user));
    
    LocalStorage

SessionStorage

  • 記憶體限制:每個域也大約為 5MB。
  • 最適合:與 LocalStorage 類似,但瀏覽器會話結束時資料會遺失,所以對於臨時儲存(如表單輸入)很有用。
    // 資料儲存到sessionStorage
    sessionStorage.setItem("name", "kuku");
    
    // 從sessionStorage取得已儲存的數據
    const name = sessionStorage.getItem("name");
    
    SessionStorage

🔔 LocalStorage vs SessionStorage:
這樣有看出差別了嗎?關閉瀏覽器 SessionStorage 存的內容就會遺失,但是 LocalStorage 還在的!
LocalStorage vs SessionStorage

IndexedDB

MDN文件:使用 IndexedDBWindow:indexedDB 属性
參考文章:前端如何緩存大筆資料:IndexedDB 介紹/應用

  • 記憶體限制:可能差異很大,但通常為 50MB 以上,感覺有時後沒有真正的限制,可能取決於使用者的可用磁碟空間。

  • 最適合:複雜的結構化資料儲存,適用於離線應用程式或需要大量客戶端資料管理的應用程式。

    語法說明:

    功能 語法 說明
    開啟數據庫 indexedDB.open() 創建或打開一個數據庫
    添加數據 add() 數據添加到對象存儲區
    讀取數據 get() 根據主鍵讀取數據
    更新數據 onupgradeneeded 當數據庫版本更新時觸發,通常用來創建對象存儲區和索引
    刪除數據 delete() 根據主鍵刪除數據
    處理事件 onsuccessonerror 處理成功和錯誤事件
    // 打開或創建數據庫
    const request = indexedDB.open('myDatabase', 1);
    
    request.onupgradeneeded = function(event) {
        const db = event.target.result;
        // 創建一個對象存儲區
        const objectStore = db.createObjectStore('myObjectStore', { keyPath: 'id' });
        objectStore.createIndex('name', 'name', { unique: false });
    };
    
    request.onsuccess = function(event) {
        const db = event.target.result;
        console.log('數據庫打開成功!');
    
        // 添加數據
        const transaction = db.transaction(['myObjectStore'], 'readwrite');
        const objectStore = transaction.objectStore('myObjectStore');
    
        const data = { id: 1, name: 'Alice' };
        const addRequest = objectStore.add(data);
    
        addRequest.onsuccess = function() {
            console.log('數據添加成功!');
        };
    
        // 讀取數據
        const getRequest = objectStore.get(1);
        getRequest.onsuccess = function() {
            console.log('讀取的數據:', getRequest.result);
        };
    
        // 刪除數據
        const deleteRequest = objectStore.delete(1);
        deleteRequest.onsuccess = function() {
            console.log('數據刪除成功!');
        };
    
        // 交易結束
        transaction.oncomplete = function() {
            console.log('所有操作完成!');
        };
    
        transaction.onerror = function(event) {
            console.error('交易失敗:', event.target.error);
        }
    

WebSQL

  • 記憶體限制:通常為 5MB,但可能有所不同。
  • 最適合:已棄用,改用 IndexedDB,提供關聯式資料儲存。

IndexedDB vs Laravel ORM


建議參考文章:後端小白自學 Laravel - 第 6 天:數據庫操作基礎

IndexedDB 和 Laravel 的數據庫在基本功能上有相似之處,但是還是有些不同啦!這裡只是想表達兩者都支持基本的 CRUD(創建、讀取、更新、刪除)操作,只是透過不同 API 操作 IndexedDB API 和 Eloquent ORM。

而且兩邊也有 transaction 防範機制,也就是寫入的時候萬一出現了異常,交易將會自動回滾,避免異常造成資料庫爆了!

但是...

他們還是有個最大的不同,存放位置!

方法 IndexedDB Laravel ORM
存放位置 數據存儲在用戶的瀏覽器 數據存儲在後端伺服器
訪問方式 用 JavaScript 在瀏覽器中訪問,主要用於網頁應用 用 PHP 代碼和後端 API 進行訪問
同步 數據存儲在用戶的設備上,可能會出現沒辦法及時同步 數據集中管理的,與服務器的數據庫同步相對簡單

上一篇
第 26 天:安全最佳實踐
下一篇
第 28 天:JavaScript 設計模式
系列文
30天 JavaScript 提升計畫:從零到精通結合2024年的創新功能30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言